home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Source Code ƒ / Misc. Pascal ƒ / Jay's Cookie / Cookie.p < prev    next >
Encoding:
Text File  |  1990-06-15  |  18.2 KB  |  681 lines  |  [TEXT/MPS ]

  1. {
  2.     File Cookie.p
  3.  
  4.     Programmer:    D. Jay Newman        1/27/89
  5.     DA which does Fortune Cookies.
  6.     I release this into the public domain.
  7.  
  8.     The data file with all the cookie information must be in your
  9.     active system folder, and the name is specified in an STR#
  10.     resource (right now it is "Fortunes").
  11.  
  12.     The data format of the fortune cookie file is the following:
  13.             Number of Cookies:    LONGINT
  14.             List of offsets:        ARRAY OF LONGINT (offsets from the
  15.                                                         start of the TEXT)
  16.             Offset of EOF:            LONGINT
  17.             Text of cookies:        Text (no separators between cookies)
  18.  
  19.     This means 3 file reads at the start, and 2 more for each additional
  20.     cookie is wanted; the speed is pretty good on my Mac II's hard disk,
  21.     but if it becomes a problem, well, this isn't a necessary program.
  22.  
  23.     Things to do later: I would like to add some data compression, but I
  24.     haven't gotten around to it; I would also like to write a cookie editor,
  25.     rather than the tool to convert a text file into a cookie file.
  26. }
  27.  
  28. {$R-} { No range checking  }
  29.  
  30. UNIT Memory;
  31.  
  32. INTERFACE
  33.  
  34. USES
  35.     MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf;
  36.  
  37.  
  38. FUNCTION DRVROpen            (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  39. FUNCTION DRVRControl    (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  40. FUNCTION DRVRStatus     (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  41. FUNCTION DRVRPrime        (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  42. FUNCTION DRVRClose        (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  43.             
  44.  
  45. IMPLEMENTATION
  46.  
  47. TYPE
  48.     EventPtr     = ^EventRecord;
  49.     trix =    RECORD                        {Needed for some coercive behavior }
  50.         CASE Boolean of
  51.             TRUE:        (FayWray: ARRAY[0..10] OF Integer);
  52.             FALSE:    (Away:    EventPtr);
  53.         END;
  54.  
  55.     MyDataRec     = RECORD
  56.         numCookies:        LONGINT;                {number of fortune cookies in file}
  57.         cookRefNum:        INTEGER;                {the refNum of the cookie file}
  58.         theTEH:                TEHandle;                {Handle to TE record for the displayed cookie}
  59.         qSeed:                LONGINT;                {Seed for random number generator}
  60.         theButton:        ControlHandle;    {Remember the button}
  61.         theScroll:        ControlHandle;    {And don't forget the bar}
  62.         theRect:            Rect;                        {Original rects for TEHandle}
  63.         pRect:                Rect;                        {Comparison portRect: if changed, fix stuff}
  64.     END;
  65.  
  66.     MyDataPtr        = ^MyDataRec;
  67.     MyDataHndl    = ^MyDataPtr;
  68.  
  69.     RectPtr            = ^Rect;
  70.     RectHandle    = ^RectPtr;
  71.  
  72. CONST
  73.     kScrollWidth    =    16;
  74.  
  75.     kMargin                =    5;
  76.     kRightMarg        =    kScrollWidth;
  77.     kBotMarg            =    43;
  78.  
  79.     kButtonLeft        =    100;                            {80 from right edge of window}
  80.     kButtonRight    =    30;                                {10 from right edge of window}
  81.     kButtonTop        =    38;
  82.     kButtonBottom    =    18;
  83.  
  84.     kMaxRandNum        =    $7FFFFFFF;                {The maximum random number}
  85.     kMinRandNum        =    0;                                {The smallest possible random number}
  86.  
  87.  
  88. FUNCTION RsrcID(dCtl: DCtlPtr): Integer;
  89. BEGIN
  90.     RsrcID := (BOR($C000,(BSL(BNOT(dCtl^.dCtlRefNum),5))));
  91. END;
  92.  
  93.  
  94. {Get a longint stored in a file at a given position from the begining; if
  95.         position = -1, then do not set the position}
  96. FUNCTION GetLongInt (fRefNum: INTEGER; position: LONGINT; VAR theNum: LONGINT): OSErr;
  97. VAR
  98.     aLen:            LONGINT;        {the length off the read}
  99.     err:            OSErr;
  100. BEGIN
  101.         IF position >= 0 THEN
  102.             err := SetFPos (fRefNum, FsFromStart, position);
  103.  
  104.         aLen := SizeOf (LONGINT);
  105.         GetLongInt := FSRead (fRefNum, aLen, @theNum);
  106. END;
  107.  
  108.  
  109. {A simple replacement for the random function, to get around having to do
  110.     weird things to the QuickDraw globals to effect the global randSeed under
  111.     MultiFinder}
  112. FUNCTION Rndom (seed: LONGINT): LONGINT;
  113. BEGIN
  114. (*
  115.     Rndom := (seed * 16807) MOD 2147483647;
  116. *)
  117.     Rndom := BAND (seed * 452807053, $7FFFFFFF);
  118. END;
  119.  
  120.  
  121. {Set the values for the scroll bar, depending upon the TE stuff}
  122. PROCEDURE SetScrollValues (aTEH: TEHandle; scrollBar: ControlHandle);
  123. VAR
  124.     lines:        INTEGER;        {Number of lines of text}
  125.     max:            INTEGER;        {Max value for control}
  126. BEGIN
  127.     WITH aTEH^^ DO
  128.         BEGIN
  129.             lines := nLines;
  130.             max := lines - ((viewRect.bottom - viewRect.top) DIV lineHeight);
  131.         END;
  132.  
  133.     IF max < 0 THEN max := 0;
  134.     SetCtlMax (scrollBar, max);
  135.     SetCtlValue (scrollBar, 0);
  136. END;
  137.  
  138.  
  139. FUNCTION GetCookie (myHandle: MyDataHndl): BOOLEAN;
  140. VAR
  141.     nCookies:            LONGINT;        {Number of cookies in file}
  142.     theRefNum:        INTEGER;        {Ref number of cookie data file}
  143.     theCookie:        LONGINT;        {The index of the cookie choosen}
  144.     cookieStart:    LONGINT;        {Start of first cookie}
  145.     cookiePos:        LONGINT;        {Offset of cookie choosen}
  146.     cookLen:            LONGINT;        {Length of cookie}
  147.     theResult:        OSErr;            {A container for the results of I/O operations}
  148.     aLong:                LONGINT;        {A LONGINT container for general use}
  149.     theText:            Handle;            {Handle for the text of the cookie}
  150.     theRndNum:        LONGINT;        {Random number}
  151.     cookieTEH:        TEHandle;        {Handle to TE record for displayed cookie}
  152. BEGIN
  153.     {Get the information from the handle}
  154.     WITH myHandle^^ DO
  155.         BEGIN
  156.             nCookies := numCookies;
  157.             theRefNum := cookRefNum;
  158.             cookieTEH := theTEH;
  159.             theRndNum := qSeed;
  160.         END;
  161.  
  162.     cookieStart := (nCookies + 2) * SizeOf (LONGINT);    {Start of cookie text in file}
  163.  
  164.     theCookie := nCookies + 1;                                                {Make it loop at least once}
  165.  
  166.     theRndNum := Rndom (theRndNum);
  167.     myHandle^^.qSeed := theRndNum;                                            {Remember random seed}
  168.  
  169.     theCookie := theRndNum DIV (kMaxRandNum DIV nCookies);
  170.  
  171.     WHILE (theCookie > nCookies) OR (theCookie < 0) DO
  172.         BEGIN
  173.             theRndNum := Rndom (theRndNum);
  174.         END;
  175.  
  176.     {Read the index of the choosen cookie}
  177.     aLong := theCookie * SizeOf (LONGINT);
  178.     theResult := GetLongInt (theRefNum, aLong, cookiePos);
  179.  
  180.     {Get the index of the following cookie}
  181.     theResult := GetLongInt (theRefNum, aLong + SizeOf (LONGINT), cookLen);
  182.     cookLen := cookLen - cookiePos;
  183.  
  184.     theResult := SetFPos (theRefNum, FSFromStart, cookieStart + cookiePos);
  185.  
  186.     theText := cookieTEH^^.hText;
  187.     SetHandleSize (theText, cookLen);
  188.  
  189.     HLock (theText);
  190.     theResult := FSRead (theRefNum, cookLen, theText^);    {Read the cookie}
  191.     HUnlock (theText);
  192.  
  193.     cookieTEH^^.viewRect := myHandle^^.theRect;
  194.     cookieTEH^^.destRect := myHandle^^.theRect;
  195.     TECalText (cookieTEH);
  196.  
  197.     {Remember, set the new maximum for the scrollbar}
  198.     SetScrollValues (cookieTEH, myHandle^^.theScroll);
  199.  
  200.     GetCookie := TRUE;
  201. END;
  202.  
  203.  
  204. FUNCTION ButtonPosition (r: Rect): Rect;
  205. BEGIN
  206.     {Position the button relative to the portRect}
  207.     r.top := r.bottom - kButtonTop;
  208.     r.bottom := r.bottom - kButtonBottom;
  209.     r.left := r.right - kButtonLeft;
  210.     r.right := r.right - kButtonRight;
  211.  
  212.     ButtonPosition := r;
  213. END;
  214.  
  215.  
  216. FUNCTION TEPosition (r: Rect; aTEH: TEHandle): Rect;
  217. BEGIN
  218.     {Position the TE field relative to the portRect}
  219.     r.bottom := r.bottom - kBotMarg;                                {Don't hide button}
  220.     r.bottom := r.bottom -
  221.                 ((r.bottom - r.top + 3) MOD aTEH^^.lineHeight);
  222.     r.right := r.right - kRightMarg;                                {Standard scroll bar width}
  223.     InsetRect (r, 5, 5);
  224.  
  225.     TEPosition := r;
  226. END;
  227.  
  228.  
  229. FUNCTION SBarPosition (r: Rect): Rect;
  230. BEGIN
  231.     r.left := r.right - kScrollWidth + 1;
  232.     r.right := r.right + 1;
  233.     r.top := r.top - 1;
  234.     r.bottom := r.bottom - kScrollWidth + 2;
  235.  
  236.     SBarPosition := r;
  237. END;
  238.  
  239.  
  240. FUNCTION DRVROpen (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  241.  
  242.     {Open the cookie file in the system folder}
  243.     FUNCTION OpenCookieFile (fileName: Str255; VAR fRefNum: INTEGER): OSErr;
  244.     VAR
  245.         aHPB:                HParamBlockRec;        {for the PBHGerVInfo call}
  246.         err:                OSErr;                        {the result of the call}
  247.         xErr:                OSErr;                        {a throw-away error}
  248.         oldVol:            INTEGER;                    {save old volume}
  249.         ioWDDirID:    LONGINT;
  250.     BEGIN
  251.         WITH aHPB DO
  252.             BEGIN
  253.                 ioCompletion := NIL;
  254.                 ioNamePtr := NIL;                {there because something is necessary}
  255.                 ioVRefNum := 0;                    {for default volume}
  256.                 ioVolIndex := 0;                {not an indexed call}
  257.             END;
  258.         err := PBHGetVInfo (@aHPB, FALSE);
  259.  
  260.         WITH aHPB DO
  261.             BEGIN
  262.                 ioCompletion := NIL;
  263.                 ioNamePtr := NIL;
  264.                 ioVRefNum := 0;
  265.                 ioWDDirID := aHPB.ioVFndrInfo [1];
  266.             END;
  267.  
  268.         err := GetVol (NIL, OldVol);
  269.         err := PBHSetVol (@aHPB, FALSE);        {Get to blessed folder}
  270.  
  271.         IF err = 0 THEN
  272.             BEGIN
  273.                 err := FSOpen (fileName, 0, fRefNum);
  274.                 xErr := SetVol (NIL, oldVol);        {Restore old current folder}
  275.             END;
  276.  
  277.         OpenCookieFile := err;
  278.     END;
  279.  
  280.  
  281.     FUNCTION GetRandomSeed: LONGINT;
  282.     VAR
  283.         secs:            LONGINT;            {A bit risque, but what the heck}
  284.     BEGIN
  285.         GetDateTime (secs);            {A lot of seconds}
  286.  
  287.         secs := BXOR (secs, TickCount);
  288.         IF (secs MOD 2) = 0 THEN
  289.             secs := secs + 1;            {Always have odd seed, not a bad one}
  290.  
  291.         GetRandomSeed := BXOR (secs, TickCount);
  292.     END;
  293.  
  294.  
  295.     {Remember the last position of the window, and if not, fake it}
  296.     PROCEDURE PutWindowInPlace;
  297.     VAR
  298.         curRes:            INTEGER;        {Ref num for current resource file}
  299.         r:                    Rect;                {Rect for window}
  300.         rHandle:        RectHandle;    {Handle for resource}
  301.     BEGIN
  302.         curRes := CurResFile;                                        {Save current resource file}
  303.         IF curRes <> 0 THEN
  304.             UseResFile (0);                                                {Use system file}
  305.  
  306.         rHandle := RectHandle (GetResource ('WhAt', RsrcID (dCtl)));
  307.         IF rHandle <> NIL THEN
  308.             r := rHandle^^
  309.         ELSE
  310.             SetRect (r, 40, 40, 200, 100);
  311.  
  312.         IF curRes <> 0 THEN                                            {Be nice and return resource file}
  313.             UseResFile (curRes);
  314.  
  315.         MoveWindow (dCtl^.dCtlWindow, r.left, r.top, FALSE);
  316.         SizeWindow (dCtl^.dCtlWindow, r.right - r.left, r.bottom - r.top, FALSE);
  317.     END;
  318.  
  319.  
  320. VAR
  321.     SavePort:        GrafPtr;                {place to save old grafPort}
  322.     nCookies:        LONGINT;                {number of cookies in file}
  323.     myWindow:        WindowPtr;            {window pointer}
  324.     cookName:        Str255;                    {name of cookie file}
  325.     cRefNum:        INTEGER;                {RefNum for cookie file}
  326.     theResult:    OSErr;                    {stuff to bypass error checking, add later}
  327.     aTEH:                TEHandle;                {TE handle to display stuff}
  328.     txRect:            Rect;                        {rectangle for TE}
  329.     myHandle:        MyDataHndl;            {handle to device storage}
  330.     aControl:        ControlHandle;    {Control handle to create controls}
  331.     r:                    Rect;                        {Rect for the window (and button)}
  332.     aHandle:        Handle;                    {A handle to avoid problems with memory}
  333. BEGIN                                                            {DRVROpen}
  334.     IF dCtl^.dCtlWindow = NIL THEN
  335.         BEGIN
  336.             GetPort (SavePort);
  337.  
  338.             {Find the cookie file name, then get the number of cookies}
  339.             GetIndString(cookName, RsrcID (dCtl), 1);
  340.  
  341.             theResult := OpenCookieFile (cookName, cRefNum);
  342.             IF theResult <> noErr THEN
  343.                 BEGIN
  344.                     DRVROpen := theResult;
  345.                     EXIT (DRVROpen);
  346.                 END;
  347.  
  348.             {Allocate storage}
  349.             myHandle := MyDataHndl (NewHandle (SizeOf (MyDataRec)));
  350.  
  351.             dCtl^.dCtlStorage := Handle (myHandle);
  352.  
  353.             myHandle^^.qSeed := GetRandomSeed;                    {Initialize random number gen}
  354.  
  355.             myWindow := GetNewWindow (RsrcID(dCtl), NIL, POINTER(-1));
  356.             windowpeek(myWindow)^.WindowKind := dCtl^.dCtlRefNum;
  357.                                                         {show a DA owns this window}
  358.             dCtl^.dCtlWindow := myWindow;                        {let the desk manager know too }
  359.  
  360.             PutWindowInPlace;
  361.  
  362.             ShowWindow (myWindow);
  363.             SetPort (myWindow);                                                {Set up port parameters}
  364.  
  365.             myHandle^^.pRect := myWindow^.portRect;        {Save for now}
  366.  
  367.             r := ButtonPosition (myWindow^.portRect);    {Set up button's rect}
  368.             aControl := NewControl (myWindow, r, 'Another', TRUE,
  369.                         0, 0, 0, pushButProc, 0);                        {Make the button}
  370.             myHandle^^.theButton := aControl;
  371.  
  372.             myHandle^^.cookRefNum := cRefNum;
  373.  
  374.             {Get number of cookies}
  375.             theResult := GetLongInt (cRefNum, 0, nCookies);
  376.             myHandle ^^.numCookies := nCookies;
  377.  
  378.             {Set up the font used}
  379.             TextFont (applFont);
  380.             TextFace ([]);
  381.             TextMode (srcCopy);
  382.             TextSize (12);
  383.  
  384.             {Initialize theTEH}
  385.             aTEH := TENew (r, r);                                                {Create with any rect}
  386.             r := TEPosition (myWindow^.portRect, aTEH);    {Now calculate real rects}
  387.  
  388.             myHandle^^.theTEH := aTEH;
  389.             myHandle^^.theRect := r;
  390.  
  391.             r := SBarPosition (myWindow^.portRect);            {Set up scroll bars}
  392.  
  393.             aControl := NewControl (myWindow, r, '', TRUE,
  394.                         0, 0, 32767, scrollBarProc, Ord4 (aTEH));    {Make the scroll bar}
  395.             myHandle^^.theScroll := aControl;
  396.  
  397.             {Get first cookie}
  398.             IF GetCookie (myHandle) THEN;
  399.  
  400.             SetPort (SavePort);
  401.         END;
  402.     DRVROpen := noErr;
  403. END;
  404.  
  405.  
  406. FUNCTION DRVRClose (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  407. VAR
  408.     myHandle:        MyDataHndl;
  409.     anOSErr:        OSErr;
  410.     refNum:            INTEGER;
  411.     rHandle:        RectHandle;
  412.     r:                    Rect;
  413.     p:                    Point;
  414.     resID:            INTEGER;
  415. BEGIN
  416.     IF dCtl^.dCtlWindow <> NIL THEN
  417.         BEGIN
  418.             myHandle := MyDataHndl (dCtl^.dCtlStorage);
  419.  
  420.             refNum := CurResFile;
  421.             IF refNum <> 0 THEN
  422.                 UseResFile (0);                                                {Use system file}
  423.  
  424.             resID := RsrcID (dCtl);
  425.             rHandle := RectHandle (GetResource ('WhAt', resID));
  426.  
  427.             r := dCtl^.dCtlWindow^.portRect;                {Get position}
  428.             p := dCtl^.dCtlWindow^.portBits.bounds.topLeft;
  429.  
  430.             r.top := r.top - p.v;                                    {Convert to global}
  431.             r.left := r.left - p.h;
  432.             r.bottom := r.bottom - p.v;
  433.             r.right := r.right - p.h;
  434.  
  435.             IF rHandle <> NIL THEN
  436.                 BEGIN
  437.                     IF NOT EqualRect (rHandle^^, r) THEN
  438.                         BEGIN
  439.                             rHandle^^ := r;
  440.                             ChangedResource (Handle (rHandle));
  441.                         END;
  442.                 END
  443.             ELSE
  444.                 BEGIN
  445.                     rHandle := RectHandle (NewHandle (SizeOf (Rect)));
  446.                     rHandle^^ := r;
  447.                     AddResource (Handle (rHandle), 'WhAt', resID, 'Cook''s WhereAt');
  448.                 END;
  449.  
  450.             IF refNum <> 0 THEN                                            {Be nice and return resource file}
  451.                 UseResFile (refNum);
  452.  
  453.             anOSErr := FSClose (myHandle^^.cookRefNum);        {Close cookie file}
  454.  
  455.             TEDispose (myHandle^^.theTEH);                                {Get rid of TEHandle;
  456.                                                                                                                 it gets rid of hText}
  457.             DisposHandle (Handle (myHandle));                            {Get rid of storage}
  458.             DisposeWindow (WindowPtr(dCtl^.dCtlWindow));    {Get rid of window}
  459.             dCtl^.dCtlWindow := NIL;
  460.         END;
  461.     DRVRClose := NOErr;
  462. END;
  463.  
  464.  
  465. PROCEDURE MyScrollProc (control: ControlHandle; part: INTEGER);
  466. VAR
  467.     amount:                    INTEGER;
  468.     aTEH:                        TEHandle;
  469.     value:                    INTEGER;
  470.     max:                        INTEGER;
  471. BEGIN
  472.     IF part <> 0 THEN
  473.         BEGIN
  474.             aTEH := TEHandle (GetCRefCon (control));
  475.  
  476.             CASE part OF
  477.                 inUpButton, inDownButton:
  478.                     amount := 1;
  479.  
  480.                 inPageUp, inPageDown:
  481.                     WITH aTEH^^ DO
  482.                         amount := (viewRect.bottom - viewRect.top) DIV lineHeight;
  483.                 END;
  484.  
  485.             IF (part = inDownButton) OR (part = inPageDown) THEN
  486.                 amount := -amount;
  487.  
  488.             {Set the actual amount, taking into account min and max}
  489.             value := GetCtlValue (control);
  490.             max := GetCtlMax (control);
  491.             amount := value - amount;
  492.  
  493.             IF amount < 0 THEN
  494.                 amount := 0
  495.             ELSE IF amount > max THEN
  496.                 amount := max;
  497.  
  498.             SetCtlValue (control, amount);
  499.             amount := value - amount;                        {Make this be the amount changed}
  500.  
  501.             IF amount <> 0 THEN
  502.                 TEScroll (0, amount * aTEH^^.lineHeight, aTEH);        {Actually scroll}
  503.         END;
  504. END;
  505.  
  506.  
  507. FUNCTION DRVRControl(ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  508. VAR
  509.     eventAt:            EventPtr;                        {Pointer to our event}
  510.     myHandle:            MyDataHndl;                    {Handle to our personal data}
  511.     aButton:            ControlHandle;            {Our button}
  512.     p:                        Point;                            {Point clicked at for button}
  513.     theText:            Handle;                            {Text for copying}
  514.     aTEH:                    TEHandle;                        {Handle to the cookie TERecord}
  515.  
  516.     PROCEDURE DrawWindow;
  517.     VAR
  518.         r:        Rect;
  519.     BEGIN    {DrawWindow}
  520.         {
  521.             If the saved portRect (myHandle^^.pRect) doesn't equal the actual
  522.              portRect, then we have to recalculate the text and button positions
  523.         }
  524.         IF NOT EqualRect (myHandle^^.pRect, dCtl^.dCtlWindow^.portRect) THEN
  525.             BEGIN
  526.                 r := dCtl^.dCtlWindow^.portRect;
  527.                 myHandle^^.pRect := r;
  528.                 EraseRect (r);
  529.                 myHandle^^.theButton^^.contrlRect := ButtonPosition (r);
  530.                 myHandle^^.theScroll^^.contrlRect := SBarPosition (r);
  531.                 r := TEPosition (r, aTEH);
  532.                 aTEH^^.viewRect := r;
  533.                 aTEH^^.destRect := r;
  534.                 myHandle^^.theRect := r;            {Save rect for later}
  535.                 TECalText (aTEH);
  536.                 SetScrollValues (aTEH, myHandle^^.theScroll);
  537.             END
  538.         ELSE
  539.             EraseRect (aTEH^^.destRect);
  540.  
  541.         TEUpdate (aTEH^^.destRect, aTEH);                                    {Draw text}
  542.  
  543.         DrawControls (dCtl^.dCtlWindow);                                    {Draw button and SBar}
  544.         DrawGrowIcon (dCtl^.dCtlWindow);                                    {Draw the grow Icon}
  545.     END;        {DrawWindow}
  546.  
  547.  
  548.     {Do whatever is necessary for handling controls}
  549.     PROCEDURE CheckControls (gp: Point);
  550.     VAR
  551.         aWindow:        WindowPtr;                {Pointer to window, hopefully mine}
  552.         aControl:        ControlHandle;        {Control handle for FindControl}
  553.         aPart:            INTEGER;                    {Which part of window or control}
  554.         r:                    Rect;                            {Used to pass min/max window sizes}
  555.         newSize:        LONGINT;                    {passed back from GrowWindow}
  556.         value:            INTEGER;                    {The value of the scrollbar}
  557.         p:                    Point;                        {The point in local coords} 
  558.     BEGIN
  559.         p := gp;
  560.         GlobalToLocal (p);
  561.  
  562.         r := dCtl^.dCtlWindow^.portRect;
  563.         r.top := r.bottom - 16;
  564.         r.left := r.right - 16;
  565.  
  566.         IF PtInRect (p, r) THEN
  567.             BEGIN
  568.                 {Grow the window}
  569.                 aWindow := dCtl^.dCtlWindow;
  570.                 SetRect (r, 100, 100, 640, 400);
  571.                 newSize := GrowWindow (aWindow, gp, r);
  572.                 IF newSize <> 0 THEN
  573.                     BEGIN
  574.                         SizeWindow (aWindow, LoWrd (newSize),
  575.                                 HiWrd (newSize), FALSE);
  576.                         InvalRect (aWindow^.portRect);
  577.                     END;
  578.             END
  579.  
  580.         ELSE
  581.             BEGIN
  582.                 aPart := FindControl (p, dCtl^.dCtlWindow, aControl);
  583.  
  584.                 IF aPart <> 0 THEN
  585.                     BEGIN                                                                                        {Yes, was a control}
  586.                         IF GetCRefCon (aControl) = 0 THEN                            {Is the button!}
  587.                             BEGIN
  588.                                 IF TrackControl (aControl, p, NIL) <> 0 THEN
  589.                                     BEGIN                                                                        {Yes, button clicked}
  590.                                         IF GetCookie (myHandle) THEN;
  591.                                         InvalRect (dCtl^.dCtlWindow^.portRect);
  592.                                     END;
  593.                             END
  594.                         ELSE
  595.                             BEGIN                                                                            {Must be scroll bar}
  596.                                 IF aPart = inThumb THEN                                    {Handle thumb as special case}
  597.                                     BEGIN
  598.                                         value := GetCtlValue (aControl);
  599.                                         IF TrackControl (aControl, p, NIL) <> 0 THEN    {If 0, do nothing}
  600.                                             BEGIN
  601.                                                 value := value - GetCtlValue (aControl);
  602.                                                 IF value <> 0 THEN
  603.                                                     TEScroll (0, value * aTEH^^.lineHeight, aTEH);
  604.                                             END;
  605.                                     END
  606.                                 ELSE
  607.                                     value := TrackControl (aControl, p, @myScrollProc);
  608.                             END;
  609.                     END;
  610.             END;
  611.     END;
  612.  
  613.  
  614.     PROCEDURE DoAccEvent;
  615.     BEGIN
  616.         CASE eventAt^.what OF
  617.             UpdateEvt:                                                            {Update Event}
  618.                 BEGIN
  619.                     BeginUpdate (WindowPtr(eventAt^.message));
  620.                     DrawWindow;
  621.                     EndUpdate (WindowPtr(eventAt^.message));
  622.                 END;
  623.  
  624.             mouseDown:                                                {MouseDown Event, might be control}
  625.                 BEGIN
  626.                     CheckControls (eventAt^.where);
  627.                 END;
  628.  
  629.             keyDown, autoKey:
  630.                 BEGIN
  631.                     SysBeep (0);
  632.                 END;
  633.         END;        {accEvent}
  634.     END;
  635.  
  636.  
  637.     PROCEDURE DoCopy;
  638.     BEGIN
  639.         IF ZeroScrap <> 0 THEN;                                        {Returns a LONGINT}
  640.         theText := myHandle^^.theTEH^^.hText;
  641.         HLock (theText);
  642.         IF PutScrap (GetHandleSize (theText), 'TEXT', theText^) <> 0 THEN;
  643.         HUnlock (theText);
  644.     END;
  645.  
  646.  
  647. BEGIN                                                                             {DRVRControl}
  648.     SetPort(GrafPtr(dCtl^.dCtlWindow));
  649.     myHandle := MyDataHndl (dCtl^.dCtlStorage);
  650.     aTEH := myHandle^^.theTEH;
  651.  
  652.     CASE ctlPB^.csCode OF
  653.         accEvent:    
  654.             BEGIN
  655.                 eventAt := trix(ctlPB^.CSParam).Away;            {get the event pointer}
  656.                 DoAccEvent;
  657.             END;
  658.  
  659.         accCopy, accCut:
  660.             BEGIN
  661.                 DoCopy;
  662.             END;
  663.     END;        {CASE}
  664.     DRVRControl := NoErr;
  665. END;     {DRVRControl}
  666.  
  667.  
  668. FUNCTION DRVRPrime (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  669. BEGIN
  670.     DRVRPrime := NoErr;
  671. END;
  672.  
  673. FUNCTION DRVRStatus (ctlPB: ParmBlkPtr; dCtl: DCtlPtr): OSErr;
  674. BEGIN
  675.     DRVRStatus := NoErr;
  676. END;
  677.  
  678.  
  679. END. {UNIT Cookie}
  680.  
  681.